1. Overview
In this document we challenge you with the following: Can you make a classification task better than a simple Neural Network? While challenging you against Neural Network, you will learn how Neural Network works and you will learn a bit more what Artifical Intelligence is, at least in the simplest implementation. In this document when we speak about Neural Network we refer to Artificial Neural Network.
In the following you will find:
- Chapter 2: we will describe the challenge that is classify the Iris Flower species based on key flower characteristics. Even if you don’t want to create your model, read this part to understand the Neural Network learning process.
- Chapter 3: we will explain the Neural Network learning metodology, based on training phase and testing phase.
- Chapter 4: we will briefly explain what a Neural Network is.
- Chapter 5: we will build two Neural Networks and test how well they can classify the Iris Flower, so you can see if you can do it better than Neural Network or not. For you to know, the Neural Network here will reach 96% correct answers! So you have to do better than this! But don’t be afraid if you can’t, you will understand why at the end.
2. The Challenge: Classify Iris Flower
Do you know Iris Flower? The Iris flower species recognition is a typical task to test Algorithms classification, so we will use this test to verify if you can classifiy Iris Flower better than a simple Neural Network.
The Iris flower can be classified according to the three species: Setosa, Versicolor and Virginica.
As we want to challenge you against a Simple Neural Network to keep it easy and understandable, we will not base our classification on images, but on length and width of Petal and Sepal. As you can see in the following picture, the three types of Iris have different shapes, and it is important to know that they can be classified based on lenght - width of Sepal and Petal, as you can see in the following images:
You try to classify the Iris with this Data!
Now the challenge for you is to try to find “rules” to classify the Iris Flower based on the following 100 Samples. They are basically 100 examples of real Iris flowers, for each Flower you have the Sepal Length, Sepal Width the Petal Length and the Petal Width.
Table 1 - Data to learn about Iris Species classification
The rules that you can find from the above real data are basically defining what you learnt about the Iris Flower. But to test your rules, in other words to test what you learnt, you are required to Classify the following 50 flowers, but in this case you have to provide the Species, and check them against the correct answer.
So hereafter you can find the list of 50 flowers you have to classify after you learnt about Iris Flower:
Table 2 - Data to provide your classification answers based on what you learnt
and here you can find the correct answers you must check against your answer. At the end you have for example 30 correct answers out of 50 cases, you have 60% correct answers. Note that they are ordered by Species for your convenience.
[1] setosa setosa setosa setosa setosa setosa setosa setosa
[9] setosa setosa setosa setosa setosa setosa setosa setosa
[17] versicolor versicolor versicolor versicolor versicolor versicolor versicolor versicolor
[25] versicolor versicolor versicolor versicolor versicolor versicolor versicolor versicolor
[33] virginica virginica virginica virginica virginica virginica virginica virginica
[41] virginica virginica virginica virginica virginica virginica virginica virginica
[49] virginica virginica
Levels: setosa versicolor virginica
Table 3 - Correct Answers to check your results
Before you test your model, if you have created one, remember that a 33% correct values can be obtain with random answers, as there are 3 possible equally distributed Species. So you must do better than 33%.
3. Neural Network learns by itself
Now regardless you have created your model or not, you understood the process we proposed to you:
- Learn about Iris Species by looking at 100 cases of iris Flowers
- Classify 50 new flowers based on what you learnt
- Test your correct answers comparing your output with the right answers
This is exactly how we will do with the Neural Network, we will Train Neural Network with 100 flowers, we will ask the trained Neural Network to classify 50 new flowers, we will check answers correcteness.
During the process we will learn how Neural Networks work. NOTE that we, as humans, are not going to teach anything to the Neural Network, in fact we might not be able to classify the Iris, even worse we might not be able to write a software program for this task, while the Neural Network is LEARNING BY ITSELF. This is the great difference between programming a Computer and let it learn with Neural Networks. Thanks to Artificial Intelligence, more precisely with Narrow Artificial Intelligence implemented with Neural Networks, the machine can do and understand things without being instructed by humans. This is actually true for other tecniques in Machine Learning, but this topic is out of scope here.
Before proceding with the training and the test, let’s see how a Neural Network looks like.
4. Some Background: What a Neural Network is
A Neural Network consists of neural units connected among them and connected with the world through input and output. So basically Neural Network has:
- one Input layer
- one outpur layer
- several hidden layers.
In the case the connections goes in one direction only from input to output such kind of Neural Network is a Feed Forward Neural Network. This is in contrast to convolutional and recursive Neural Network that have a different and more complex architecture. Here we will focus on Feed Forward Neural Network.
Each neural unit receives several numerical input, weights each input and sum the input, before sending to the output the numerical value is processed by a non linear function that is called Activation Function as showed in the following picture:
5. Let’s challenge the Neural Network to classify the Iris, can it do better than you?
As first step we have to create the Neural Network capable of classifing the Iris species. We will be using the standard method training plus testing as described in the previous paragraph.
So basicall the Neural Network will learn from examples and than will be evaluated with a classification test.
The study is based on the R package nnet, that is a simple package that support only one hidden layer but it is powerful enough to train good models and for tutorial reasons.
From previous chapters you remember that the input to classify the Iris are:
- Sepal Length
- Sepal Width
- Petal Length
- Petal Width
As we have 4 input, we need 4 neural nodes in input fed by the Sepal and Petal length and width, and 3 neural nodes in output as we have three possible output:
- setosa
- versicolor
- virginica.
For each input flower, the Neural Network provides 3 numbers, one associated to each type of Iris, the greatest value identify the answer of the network. For example if we have as output setosa = 19, versicolor = 34, virginca = 2, it means that the input flower is classified as versicolor as it has the highest value associated.
Neural Node with one single hidden node
As we said we will investigate Neural Network with only one hidden layer. To start with the simplest possible Neural Network, we will consider only one neural node in the hidden layer. the activation function we consider is the sigmoid see Figure 3.
As from the previous chapter, the only thing we have to tune now are the weigths in red as you can see in the following picture.
The Initial untrained Neural Network
The following Neural Network represents the Initial Neural Network, before training. The width of the internodes connections is proportional to the weigth. If we test this untrained network with the testing data, we actually obtain the following table, meaning that the Netowrk output is always setosa, and the accuracy is 28%, that is about 33% as expected.
The Neural Network after one learning cycle
In order to improve, the Neural Network must be fed with examples, as stated before we must go through the training steps to adjust weights and minimize the errors. Let’s see how the Neural Network improves going through one single minimization cycle, that is going through the 100 test flowers only once.
The resulting Network and results with test data as input is in the following picture.
Figure 6 - The Neural Network after one cycle training
The Neural Network after several learning cycles
As the first learning cycle didn’t improve the result, so let the Neural Network play and play again with the data set as Romans said “Repetita Iuvant”: repeating things helps! Let’s apply the default 100 repetition. After this training, the parameters tuning led to an improvement. Now the accuracy is 54%. See the following picture.
Figure 7 - The Neural Network after many cycle training.
The Neural Network with three hidden nodes
As the Accuracy is quite low for the one node hidden network, let’s try with a more complex Neural Network, in this case we increase the number of Neural Nodes in the hidden layer to 3 and perform several cycles learning.
As you can see in the following picture, the three hidden nodes Neural Network is doing much better than the previous one, reaching an accuracy of 96%.
6. Did the Neural Network do better than you?
it is very likely that the simple one hidden layer three nodes Neural Network did better than you in Iris classification. But how can a 12 nodes - 27 weights Neural Network do better than a Human Brain consisting of about \(10^{11}\) Neurons EACH with about \(10^{4}\) weights?
This is because the classification here is based on measures, that are numbers where computer are much better then us. But numbers are not the “real” world, they are abstractions of it. Human Brain in contrast is excellent to work with the real world, that is on actual flowers images rather than measures of it.
7. Conclusions
What we did: we explained the architecture of Neural Network and we have trained two simple Neural Networks based on data about how to classify the Iris species based on sepal-petal length and width. Note that this task is in the area of Narrow Artificial Intellingence, that is about doing specific, very well defined tasks.
Neural Network learn by itself: We have seen that we can train a Neural Network just by “showing” examples, there is no need to actually teach Neural Network how to do things, no need to code complex algorithms in computer program. After the training is done, the Neural Network can face real new cases, and apply to them what it learnt. The Neural Network learns by itself.
How Neural Network learns: We have shown that training a Network means actually optimizing the weights of the connections, once we have selected how many hidden layers, how many nodes per hidden layer we want and the activation function to be used. For the sake of simplicity we didn’t cover the algorithms to optimize the weights, called stochastic gradient descent with backpropagation technique.
More complex Neural Network can do better: We showed how more complex Neural Network can do better than simple ones, in our case we moved from 54% accuracy with a one hidden neural node to 96% accuracy with three hidden neural nodes.
LS0tDQp0aXRsZTogJ0FydGlmaWNpYWwgSW50ZWxsaWdlbmNlOiBIb3cgaXMgTmV1cmFsIE5ldHdvcmsgd29ya2luZywgYmV0dGVyIHRoYW4geW91PycNCmF1dGhvcjogIkx1Y2EgVmlnbmFsaSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KIyAxLiBPdmVydmlldw0KSW4gdGhpcyBkb2N1bWVudCB3ZSBjaGFsbGVuZ2UgeW91IHdpdGggdGhlIGZvbGxvd2luZzogKipDYW4geW91IG1ha2UgYSBjbGFzc2lmaWNhdGlvbiB0YXNrIGJldHRlciB0aGFuIGEgc2ltcGxlIE5ldXJhbCBOZXR3b3JrPyoqIFdoaWxlIGNoYWxsZW5naW5nIHlvdSBhZ2FpbnN0IE5ldXJhbCBOZXR3b3JrLCB5b3Ugd2lsbCBsZWFybiBob3cgKipOZXVyYWwgTmV0d29yayB3b3JrcyoqIGFuZCB5b3Ugd2lsbCBsZWFybiBhIGJpdCBtb3JlIHdoYXQgQXJ0aWZpY2FsIEludGVsbGlnZW5jZSBpcywgYXQgbGVhc3QgaW4gdGhlIHNpbXBsZXN0IGltcGxlbWVudGF0aW9uLiBJbiB0aGlzIGRvY3VtZW50IHdoZW4gd2Ugc3BlYWsgYWJvdXQgTmV1cmFsIE5ldHdvcmsgd2UgcmVmZXIgdG8gQXJ0aWZpY2lhbCBOZXVyYWwgTmV0d29yay4gDQoNCioqSW4gdGhlIGZvbGxvd2luZyB5b3Ugd2lsbCBmaW5kKio6DQoNCiogQ2hhcHRlciAyOiB3ZSB3aWxsIGRlc2NyaWJlIHRoZSBjaGFsbGVuZ2UgdGhhdCBpcyBjbGFzc2lmeSB0aGUgSXJpcyBGbG93ZXIgc3BlY2llcyBiYXNlZCBvbiBrZXkgZmxvd2VyIGNoYXJhY3RlcmlzdGljcy4gRXZlbiBpZiB5b3UgZG9uJ3Qgd2FudCB0byBjcmVhdGUgeW91ciBtb2RlbCwgcmVhZCB0aGlzIHBhcnQgdG8gdW5kZXJzdGFuZCB0aGUgTmV1cmFsIE5ldHdvcmsgbGVhcm5pbmcgcHJvY2Vzcy4gDQoqIENoYXB0ZXIgMzogd2Ugd2lsbCBleHBsYWluIHRoZSBOZXVyYWwgTmV0d29yayBsZWFybmluZyBtZXRvZG9sb2d5LCBiYXNlZCBvbiB0cmFpbmluZyBwaGFzZSBhbmQgdGVzdGluZyBwaGFzZS4NCiogQ2hhcHRlciA0OiB3ZSB3aWxsIGJyaWVmbHkgZXhwbGFpbiB3aGF0IGEgTmV1cmFsIE5ldHdvcmsgaXMuDQoqIENoYXB0ZXIgNTogIHdlIHdpbGwgYnVpbGQgdHdvIE5ldXJhbCBOZXR3b3JrcyBhbmQgdGVzdCBob3cgd2VsbCB0aGV5IGNhbiBjbGFzc2lmeSB0aGUgSXJpcyBGbG93ZXIsIHNvIHlvdSBjYW4gc2VlIGlmIHlvdSBjYW4gZG8gaXQgYmV0dGVyIHRoYW4gTmV1cmFsIE5ldHdvcmsgb3Igbm90LiBGb3IgeW91IHRvIGtub3csICoqdGhlIE5ldXJhbCBOZXR3b3JrIGhlcmUgd2lsbCByZWFjaCA5NiUgY29ycmVjdCBhbnN3ZXJzISoqIFNvIHlvdSBoYXZlIHRvIGRvIGJldHRlciB0aGFuIHRoaXMhIEJ1dCBkb24ndCBiZSBhZnJhaWQgaWYgeW91IGNhbid0LCB5b3Ugd2lsbCB1bmRlcnN0YW5kIHdoeSBhdCB0aGUgZW5kLg0KDQojIDIuIFRoZSBDaGFsbGVuZ2U6IENsYXNzaWZ5IElyaXMgRmxvd2VyDQpEbyB5b3Uga25vdyBJcmlzIEZsb3dlcj8gVGhlIElyaXMgZmxvd2VyIHNwZWNpZXMgcmVjb2duaXRpb24gaXMgYSB0eXBpY2FsIHRhc2sgdG8gdGVzdCBBbGdvcml0aG1zIGNsYXNzaWZpY2F0aW9uLCBzbyB3ZSB3aWxsIHVzZSB0aGlzIHRlc3QgdG8gdmVyaWZ5IGlmIHlvdSBjYW4gY2xhc3NpZml5IElyaXMgRmxvd2VyIGJldHRlciB0aGFuIGEgc2ltcGxlIE5ldXJhbCBOZXR3b3JrLg0KDQpUaGUgSXJpcyBmbG93ZXIgY2FuIGJlIGNsYXNzaWZpZWQgYWNjb3JkaW5nIHRvIHRoZSB0aHJlZSBzcGVjaWVzOiBTZXRvc2EsIFZlcnNpY29sb3IgYW5kIFZpcmdpbmljYS4gDQoNCkFzIHdlIHdhbnQgdG8gY2hhbGxlbmdlIHlvdSBhZ2FpbnN0IGEgU2ltcGxlIE5ldXJhbCBOZXR3b3JrIHRvIGtlZXAgaXQgZWFzeSBhbmQgdW5kZXJzdGFuZGFibGUsIHdlIHdpbGwgbm90IGJhc2Ugb3VyIGNsYXNzaWZpY2F0aW9uIG9uIGltYWdlcywgYnV0IG9uIGxlbmd0aCBhbmQgd2lkdGggb2YgUGV0YWwgYW5kIFNlcGFsLiBBcyB5b3UgY2FuIHNlZSBpbiB0aGUgZm9sbG93aW5nIHBpY3R1cmUsIHRoZSB0aHJlZSB0eXBlcyBvZiBJcmlzIGhhdmUgZGlmZmVyZW50IHNoYXBlcywgYW5kIGl0IGlzIGltcG9ydGFudCB0byBrbm93IHRoYXQgdGhleSBjYW4gYmUgY2xhc3NpZmllZCBiYXNlZCBvbiBsZW5naHQgLSB3aWR0aCBvZiBTZXBhbCBhbmQgUGV0YWwsIGFzIHlvdSBjYW4gc2VlIGluIHRoZSBmb2xsb3dpbmcgaW1hZ2VzOg0KDQoNCg0KPHAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyOyI+PGltZyBzcmM9Ii4vSVJJUy5wbmciIGFsdD0iSXJpcyIgc3R5bGU9IndpZHRoOiA1MDBweDsiPjwvcD4NCg0KIyMjIyMgRmlndXJlIDEgLSBJcmlzIEZsb3dlciBTcGVjaWVzIGFuZCBBdHRyaWJ1dGVzIHRvIGNsYXNzaWZ5IHRoZW0NCg0KSWYgeW91IGxvb2sgYXQgdGhlIEF0dHJpYnV0ZSBJbmZvcm1hdGlvbiBib3gsIHlvdSBjYW4gc2VlIFBldGFsIGFuZCBTZXBhbCBhbmQgZmV3IGV4YW1wbGUgb2YgdHJhaW5pbmcgbWF0ZXJpYWwuIExvb2tpbmcgYXQgdGhlIGZpcnN0IHJvdyBpbiB0aGUgRXhhbXBsZSA1LjMsMy43LDEuNSwwLjIsSXJpcy1TZXRvc2EsIG1lYW5zIHRoYXQgb25lIHNwZWNpZmljIGZsb3dlciwgb25lIHNhbXBsZSwgd2FzIGFuIElyaXMgU2V0b3NhIHdpdGggU2VwYWwgTGVuZ3RoID0gNS4zY20sIFNlcGFsIFdpZHRoID0gMy43Y20sIFBldGFsIExlbmd0aCA9IDEuNWNtIGFuZCBQZXRhbCBXaWR0aCA9IDAuMmNtLiAgDQoNCiMjIyBZb3UgdHJ5IHRvIGNsYXNzaWZ5IHRoZSBJcmlzIHdpdGggdGhpcyBEYXRhIQ0KDQpOb3cgdGhlIGNoYWxsZW5nZSBmb3IgeW91IGlzIHRvIHRyeSB0byBmaW5kICJydWxlcyIgdG8gY2xhc3NpZnkgdGhlIElyaXMgRmxvd2VyIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgMTAwIFNhbXBsZXMuIFRoZXkgYXJlIGJhc2ljYWxseSAxMDAgZXhhbXBsZXMgb2YgcmVhbCBJcmlzIGZsb3dlcnMsIGZvciBlYWNoIEZsb3dlciB5b3UgaGF2ZSB0aGUgU2VwYWwgTGVuZ3RoLCBTZXBhbCBXaWR0aCB0aGUgUGV0YWwgTGVuZ3RoIGFuZCB0aGUgUGV0YWwgV2lkdGguIA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0gMTB9DQpzZXQuc2VlZCg4OCkNCmkgPC0gc2FtcGxlKDE6MTUwLDEwMCkNCmlyaXNfdHJhaW4gPC0gaXJpc1tpLF0NCmlyaXNfdGVzdCA8LSBpcmlzWy1pLF0NCmlyaXNfdHJhaW4NCmBgYA0KIyMjIyMgVGFibGUgMSAtIERhdGEgdG8gbGVhcm4gYWJvdXQgSXJpcyBTcGVjaWVzIGNsYXNzaWZpY2F0aW9uDQoNClRoZSBydWxlcyB0aGF0IHlvdSBjYW4gZmluZCBmcm9tIHRoZSBhYm92ZSByZWFsIGRhdGEgYXJlIGJhc2ljYWxseSBkZWZpbmluZyB3aGF0IHlvdSBsZWFybnQgYWJvdXQgdGhlIElyaXMgRmxvd2VyLiBCdXQgdG8gdGVzdCB5b3VyIHJ1bGVzLCBpbiBvdGhlciB3b3JkcyB0byB0ZXN0IHdoYXQgeW91IGxlYXJudCwgeW91IGFyZSByZXF1aXJlZCB0byBDbGFzc2lmeSB0aGUgZm9sbG93aW5nIDUwIGZsb3dlcnMsIGJ1dCBpbiB0aGlzIGNhc2UgeW91IGhhdmUgdG8gcHJvdmlkZSB0aGUgU3BlY2llcywgYW5kIGNoZWNrIHRoZW0gYWdhaW5zdCB0aGUgY29ycmVjdCBhbnN3ZXIuDQoNClNvIGhlcmVhZnRlciB5b3UgY2FuIGZpbmQgdGhlIGxpc3Qgb2YgNTAgZmxvd2VycyB5b3UgaGF2ZSB0byBjbGFzc2lmeSBhZnRlciB5b3UgbGVhcm50IGFib3V0IElyaXMgRmxvd2VyOg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmlyaXNfdGVzdFssYygxOjQpXQ0KYGBgDQojIyMjIyBUYWJsZSAyIC0gRGF0YSB0byBwcm92aWRlIHlvdXIgY2xhc3NpZmljYXRpb24gYW5zd2VycyBiYXNlZCBvbiB3aGF0IHlvdSBsZWFybnQNCg0KYW5kIGhlcmUgeW91IGNhbiBmaW5kIHRoZSBjb3JyZWN0IGFuc3dlcnMgeW91IG11c3QgY2hlY2sgYWdhaW5zdCB5b3VyIGFuc3dlci4gQXQgdGhlIGVuZCB5b3UgaGF2ZSBmb3IgZXhhbXBsZSAzMCBjb3JyZWN0IGFuc3dlcnMgb3V0IG9mIDUwIGNhc2VzLCB5b3UgaGF2ZSA2MCUgY29ycmVjdCBhbnN3ZXJzLiBOb3RlIHRoYXQgdGhleSBhcmUgb3JkZXJlZCBieSBTcGVjaWVzIGZvciB5b3VyIGNvbnZlbmllbmNlLiANCg0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQppcmlzX3Rlc3RbLDVdDQpgYGANCiMjIyMjIFRhYmxlIDMgLSBDb3JyZWN0IEFuc3dlcnMgdG8gY2hlY2sgeW91ciByZXN1bHRzDQoNCkJlZm9yZSB5b3UgdGVzdCB5b3VyIG1vZGVsLCBpZiB5b3UgaGF2ZSBjcmVhdGVkIG9uZSwgcmVtZW1iZXIgdGhhdCBhIDMzJSBjb3JyZWN0IHZhbHVlcyBjYW4gYmUgb2J0YWluIHdpdGggcmFuZG9tIGFuc3dlcnMsIGFzIHRoZXJlIGFyZSAzIHBvc3NpYmxlIGVxdWFsbHkgZGlzdHJpYnV0ZWQgU3BlY2llcy4gU28geW91IG11c3QgZG8gYmV0dGVyIHRoYW4gMzMlLg0KDQojIDMuIE5ldXJhbCBOZXR3b3JrIGxlYXJucyBieSBpdHNlbGYNCg0KTm93IHJlZ2FyZGxlc3MgeW91IGhhdmUgY3JlYXRlZCB5b3VyIG1vZGVsIG9yIG5vdCwgeW91IHVuZGVyc3Rvb2QgdGhlIHByb2Nlc3Mgd2UgcHJvcG9zZWQgdG8geW91Og0KDQoxLiAqKkxlYXJuKiogYWJvdXQgSXJpcyBTcGVjaWVzIGJ5IGxvb2tpbmcgYXQgMTAwIGNhc2VzIG9mIGlyaXMgRmxvd2Vycw0KMi4gKipDbGFzc2lmeSoqIDUwIG5ldyBmbG93ZXJzIGJhc2VkIG9uIHdoYXQgeW91IGxlYXJudA0KMy4gKipUZXN0KiogeW91ciBjb3JyZWN0IGFuc3dlcnMgY29tcGFyaW5nIHlvdXIgb3V0cHV0IHdpdGggdGhlIHJpZ2h0IGFuc3dlcnMNCg0KVGhpcyBpcyBleGFjdGx5IGhvdyB3ZSB3aWxsIGRvIHdpdGggdGhlIE5ldXJhbCBOZXR3b3JrLCB3ZSB3aWxsIFRyYWluIE5ldXJhbCBOZXR3b3JrIHdpdGggMTAwIGZsb3dlcnMsIHdlIHdpbGwgYXNrIHRoZSB0cmFpbmVkIE5ldXJhbCBOZXR3b3JrIHRvIGNsYXNzaWZ5IDUwIG5ldyBmbG93ZXJzLCB3ZSB3aWxsIGNoZWNrIGFuc3dlcnMgY29ycmVjdGVuZXNzLg0KDQpEdXJpbmcgdGhlIHByb2Nlc3Mgd2Ugd2lsbCBsZWFybiBob3cgTmV1cmFsIE5ldHdvcmtzIHdvcmsuIE5PVEUgdGhhdCB3ZSwgYXMgaHVtYW5zLCBhcmUgbm90IGdvaW5nIHRvIHRlYWNoIGFueXRoaW5nIHRvIHRoZSBOZXVyYWwgTmV0d29yaywgaW4gZmFjdCB3ZSBtaWdodCBub3QgYmUgYWJsZSB0byBjbGFzc2lmeSB0aGUgSXJpcywgZXZlbiB3b3JzZSB3ZSBtaWdodCBub3QgYmUgYWJsZSB0byB3cml0ZSBhIHNvZnR3YXJlIHByb2dyYW0gZm9yIHRoaXMgdGFzaywgd2hpbGUgdGhlIE5ldXJhbCBOZXR3b3JrIGlzICoqTEVBUk5JTkcgQlkgSVRTRUxGKiouIFRoaXMgaXMgdGhlIGdyZWF0IGRpZmZlcmVuY2UgYmV0d2VlbiBwcm9ncmFtbWluZyBhIENvbXB1dGVyIGFuZCBsZXQgaXQgbGVhcm4gd2l0aCBOZXVyYWwgTmV0d29ya3MuIFRoYW5rcyB0byBBcnRpZmljaWFsIEludGVsbGlnZW5jZSwgbW9yZSBwcmVjaXNlbHkgd2l0aCBOYXJyb3cgQXJ0aWZpY2lhbCBJbnRlbGxpZ2VuY2UgaW1wbGVtZW50ZWQgd2l0aCBOZXVyYWwgTmV0d29ya3MsIHRoZSBtYWNoaW5lIGNhbiBkbyBhbmQgdW5kZXJzdGFuZCB0aGluZ3Mgd2l0aG91dCBiZWluZyBpbnN0cnVjdGVkIGJ5IGh1bWFucy4gVGhpcyBpcyBhY3R1YWxseSB0cnVlIGZvciBvdGhlciB0ZWNuaXF1ZXMgaW4gTWFjaGluZSBMZWFybmluZywgYnV0IHRoaXMgdG9waWMgaXMgb3V0IG9mIHNjb3BlIGhlcmUuDQoNCkJlZm9yZSBwcm9jZWRpbmcgd2l0aCB0aGUgdHJhaW5pbmcgYW5kIHRoZSB0ZXN0LCBsZXQncyBzZWUgaG93IGEgTmV1cmFsIE5ldHdvcmsgbG9va3MgbGlrZS4NCg0KDQojIDQuIFNvbWUgQmFja2dyb3VuZDogV2hhdCBhIE5ldXJhbCBOZXR3b3JrIGlzDQpBIE5ldXJhbCBOZXR3b3JrIGNvbnNpc3RzIG9mIG5ldXJhbCB1bml0cyBjb25uZWN0ZWQgYW1vbmcgdGhlbSBhbmQgY29ubmVjdGVkIHdpdGggdGhlIHdvcmxkIHRocm91Z2ggaW5wdXQgYW5kIG91dHB1dC4gU28gYmFzaWNhbGx5IE5ldXJhbCBOZXR3b3JrIGhhczoNCg0KKiBvbmUgSW5wdXQgbGF5ZXINCiogb25lIG91dHB1ciBsYXllciANCiogc2V2ZXJhbCBoaWRkZW4gbGF5ZXJzLiANCg0KSW4gdGhlIGNhc2UgdGhlIGNvbm5lY3Rpb25zIGdvZXMgaW4gb25lIGRpcmVjdGlvbiBvbmx5IGZyb20gaW5wdXQgdG8gb3V0cHV0IHN1Y2gga2luZCBvZiBOZXVyYWwgTmV0d29yayBpcyBhICoqRmVlZCBGb3J3YXJkIE5ldXJhbCBOZXR3b3JrKiouIFRoaXMgaXMgaW4gY29udHJhc3QgdG8gY29udm9sdXRpb25hbCBhbmQgcmVjdXJzaXZlIE5ldXJhbCBOZXR3b3JrIHRoYXQgaGF2ZSBhIGRpZmZlcmVudCBhbmQgbW9yZSBjb21wbGV4IGFyY2hpdGVjdHVyZS4gDQpIZXJlIHdlIHdpbGwgZm9jdXMgb24gRmVlZCBGb3J3YXJkIE5ldXJhbCBOZXR3b3JrLiANCg0KRWFjaCBuZXVyYWwgdW5pdCByZWNlaXZlcyBzZXZlcmFsIG51bWVyaWNhbCBpbnB1dCwgd2VpZ2h0cyBlYWNoIGlucHV0IGFuZCBzdW0gdGhlIGlucHV0LCBiZWZvcmUgc2VuZGluZyB0byB0aGUgb3V0cHV0IHRoZSBudW1lcmljYWwgdmFsdWUgaXMgcHJvY2Vzc2VkIGJ5IGEgbm9uIGxpbmVhciBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCAqKkFjdGl2YXRpb24gRnVuY3Rpb24qKiBhcyBzaG93ZWQgaW4gdGhlIGZvbGxvd2luZyBwaWN0dXJlOg0KDQohW10oLi9OZXVyYWxOZXR3b3JrLlBORykNCg0KIyMjIyMgRmlndXJlIDMgLSBOZXVyYWwgTmV0d29yayBBcmNoaXRlY3R1cmUNCg0KU28gdGhlIE5ldXJhbCBOZXR3b3JrIGlzIGJhc2ljYWxseSBkZWZpbmVkIGJ5Og0KDQoqIE51bWJlciBvZiBOZXVyb25zIGluIGVhY2ggbGF5ZXIuDQoqIEhvdyBtYW55IGhpZGRlbiBsYXllcnMgYXJlIHByZXNlbnQuDQoqIFRoZSB3ZWlndGggb2YgZWFjaCBpbnRlcmNvbm5lY3Rpb24uDQoqIFRoZSBhY3RpdmF0aW9uIGZ1bmN0aW9uIGF0IGVhY2ggbmV1cm9uLg0KKiBUaGUgYmlhcyBpbnB1dCB0byBlYWNoIGxheWVyLiBpbnB1dCBsYXllciBoYXMgbm8gYmlhcy4NCg0KDQojIDUuIExldCdzIGNoYWxsZW5nZSB0aGUgTmV1cmFsIE5ldHdvcmsgdG8gY2xhc3NpZnkgdGhlIElyaXMsIGNhbiBpdCBkbyBiZXR0ZXIgdGhhbiB5b3U/DQoNCkFzIGZpcnN0IHN0ZXAgd2UgaGF2ZSB0byBjcmVhdGUgdGhlIE5ldXJhbCBOZXR3b3JrIGNhcGFibGUgb2YgY2xhc3NpZmluZyB0aGUgSXJpcyBzcGVjaWVzLiBXZSB3aWxsIGJlIHVzaW5nIHRoZSBzdGFuZGFyZCBtZXRob2QgdHJhaW5pbmcgcGx1cyB0ZXN0aW5nIGFzIGRlc2NyaWJlZCBpbiB0aGUgcHJldmlvdXMgcGFyYWdyYXBoLg0KDQpTbyBiYXNpY2FsbCB0aGUgTmV1cmFsIE5ldHdvcmsgd2lsbCBsZWFybiBmcm9tIGV4YW1wbGVzIGFuZCB0aGFuIHdpbGwgYmUgZXZhbHVhdGVkIHdpdGggYSBjbGFzc2lmaWNhdGlvbiB0ZXN0Lg0KDQpUaGUgc3R1ZHkgaXMgYmFzZWQgb24gdGhlIFIgcGFja2FnZSBubmV0LCB0aGF0IGlzIGEgc2ltcGxlIHBhY2thZ2UgdGhhdCBzdXBwb3J0IG9ubHkgb25lIGhpZGRlbiBsYXllciBidXQgaXQgaXMgcG93ZXJmdWwgZW5vdWdoIHRvIHRyYWluIGdvb2QgbW9kZWxzIGFuZCBmb3IgdHV0b3JpYWwgcmVhc29ucy4NCg0KRnJvbSBwcmV2aW91cyBjaGFwdGVycyB5b3UgcmVtZW1iZXIgdGhhdCB0aGUgaW5wdXQgdG8gY2xhc3NpZnkgdGhlIElyaXMgYXJlOg0KDQoxLiBTZXBhbCBMZW5ndGgNCjIuIFNlcGFsIFdpZHRoIA0KMy4gUGV0YWwgTGVuZ3RoDQo0LiBQZXRhbCBXaWR0aA0KDQoqKkFzIHdlIGhhdmUgNCBpbnB1dCwgd2UgbmVlZCA0IG5ldXJhbCBub2RlcyBpbiBpbnB1dCoqIGZlZCBieSB0aGUgU2VwYWwgYW5kIFBldGFsIGxlbmd0aCBhbmQgd2lkdGgsIGFuZCAqKjMgbmV1cmFsIG5vZGVzIGluIG91dHB1dCBhcyB3ZSBoYXZlIHRocmVlIHBvc3NpYmxlIG91dHB1dCoqOg0KDQoxLiBzZXRvc2ENCjIuIHZlcnNpY29sb3INCjMuIHZpcmdpbmljYS4gDQoNCkZvciBlYWNoIGlucHV0IGZsb3dlciwgdGhlIE5ldXJhbCBOZXR3b3JrIHByb3ZpZGVzIDMgbnVtYmVycywgb25lIGFzc29jaWF0ZWQgdG8gZWFjaCB0eXBlIG9mIElyaXMsIHRoZSBncmVhdGVzdCB2YWx1ZSBpZGVudGlmeSB0aGUgYW5zd2VyIG9mIHRoZSBuZXR3b3JrLiBGb3IgZXhhbXBsZSBpZiB3ZSBoYXZlIGFzIG91dHB1dCBzZXRvc2EgPSAxOSwgdmVyc2ljb2xvciA9IDM0LCB2aXJnaW5jYSA9IDIsIGl0IG1lYW5zIHRoYXQgdGhlIGlucHV0IGZsb3dlciBpcyBjbGFzc2lmaWVkIGFzIHZlcnNpY29sb3IgYXMgaXQgaGFzIHRoZSBoaWdoZXN0IHZhbHVlIGFzc29jaWF0ZWQuDQoNCiMjIyBOZXVyYWwgTm9kZSB3aXRoIG9uZSBzaW5nbGUgaGlkZGVuIG5vZGUNCg0KQXMgd2Ugc2FpZCB3ZSB3aWxsIGludmVzdGlnYXRlIE5ldXJhbCBOZXR3b3JrIHdpdGggb25seSBvbmUgaGlkZGVuIGxheWVyLiBUbyBzdGFydCB3aXRoIHRoZSBzaW1wbGVzdCBwb3NzaWJsZSBOZXVyYWwgTmV0d29yaywgd2Ugd2lsbCBjb25zaWRlciBvbmx5IG9uZSBuZXVyYWwgbm9kZSBpbiB0aGUgaGlkZGVuIGxheWVyLiB0aGUgYWN0aXZhdGlvbiBmdW5jdGlvbiB3ZSBjb25zaWRlciBpcyB0aGUgKipzaWdtb2lkKiogc2VlIEZpZ3VyZSAzLg0KDQpBcyBmcm9tIHRoZSBwcmV2aW91cyBjaGFwdGVyLCB0aGUgb25seSB0aGluZyB3ZSBoYXZlIHRvIHR1bmUgbm93IGFyZSB0aGUgd2VpZ3RocyBpbiByZWQgYXMgeW91IGNhbiBzZWUgaW4gdGhlIGZvbGxvd2luZyBwaWN0dXJlLg0KDQoNCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOmNlbnRlcjsiPjxpbWcgc3JjPSIuL09uZU5vZGUxMVcucG5nIiBhbHQ9IkRyYXdpbmciIHN0eWxlPSJ3aWR0aDogNTAwcHg7Ij48L3A+DQoNCiMjIyMjIEZpZ3VyZSA0IC0gT25lIEhpZGRlbiBub2RlIE5ldXJhbCBOZXR3b3JrLiAxMSB3ZWlnaHRzIHRvIGJlIHR1bmVkLg0KDQpUaGUgdHVuaW5nIG9mIHRoZSBwYXJhbWV0ZXJzIGlzIGFjdHVhbGx5IHRoZSBsZWFybmluZyBwaGFzZSwgY2FsbGVkIGFsc28gdHJhaW5pZyBwaGFzZS4gVGhlICoqdHJhaW5pbmcgcGhhc2UqKiBmb3Igb3VyIHNpbXBsZSBjYXNlIGNvbnNpc3RzIG9mIHRoZSBmb2xsb3dpbmcgc3RlcHM6DQoNCjEuIEluaXRpYWxpemUgdGhlIDExIHdlaWdodHMgd2l0aCByYW5kb20gbnVtYmVycy4NCjIuIElucHV0IDEwMCBmbG93ZXJzIGZvciB0cmFpbmluZy4NCjMuIENvbXBhcmUgdGhlIG91dHB1dCB3aXRoIGNvcnJlY3QgYW5zd2VycyBhbmQgY2FsY3VsYXRlIGFuIGVycm9yLg0KNC4gQWRqdXN0IHRoZSB3ZWlnaHRzIC0gY2FsbGVkIGJhY2twcm9wYWdhdGlvbiBtZXRob2QgLSBhbmQgZ28gdG8gc3RlcCAyLg0KDQpUaGUgbG9vcCBpcyBhY3R1YWxseSBzdG9wcGVkIGVpdGhlciB3aGVuIHRoZSBlcnJvciBpcyBzYXRpc2ZhY3Rvcnkgb3Igd2hlbiBhIG1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbiBpcyByZWFjaGVkLg0KDQpUaG9zZSBzdGVwcyBkZWZpbmVzIGhvdyAqKnRoZSBOZXVyYWwgTmV0d29yayBsZWFybnMqKi4NCg0KSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBpZiB3ZSBzdG9wIGF0IHN0ZXAgMSwgd2UgaGF2ZSBhIHJhbmRvbSBuZXVyYWwgbmV0d29yaywgdGhhdCBpcyBpbiBvdGhlciB3b3JkcyBhbiB1bnRyYWluZWQgbmV0d29yay4NCkludGl1dGl2ZWx5IHdlIGNhbiBleHBlY3QgdGhhdCBzdWNoIGluaXRpYWwgTmV0d29yaywgdGhhdCBpcyBub3QgdHJhaW5lZCwgaXMgYmFzaWNhbGx5IHByb3ZpZGluZyByYW5kb20gb3V0cHV0LCB3aXRoIGFuIGV4cGVjdGVkIGFjY3VyYWN5IG9mIDMzJSBpbiB0aGlzIGNhc2UgYXMgd2UgaGF2ZSB0aHJlZSBwb3NzaWJsZSBvdXRwdXQuDQoNCiMjIyMgVGhlIEluaXRpYWwgdW50cmFpbmVkIE5ldXJhbCBOZXR3b3JrDQoNClRoZSBmb2xsb3dpbmcgTmV1cmFsIE5ldHdvcmsgcmVwcmVzZW50cyB0aGUgSW5pdGlhbCBOZXVyYWwgTmV0d29yaywgYmVmb3JlIHRyYWluaW5nLiBUaGUgd2lkdGggb2YgdGhlIGludGVybm9kZXMgY29ubmVjdGlvbnMgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSB3ZWlndGguIElmIHdlIHRlc3QgdGhpcyB1bnRyYWluZWQgbmV0d29yayB3aXRoIHRoZSB0ZXN0aW5nIGRhdGEsIHdlIGFjdHVhbGx5IG9idGFpbiB0aGUgZm9sbG93aW5nIHRhYmxlLCBtZWFuaW5nIHRoYXQgdGhlIE5ldG93cmsgb3V0cHV0IGlzIGFsd2F5cyBzZXRvc2EsIGFuZCB0aGUgYWNjdXJhY3kgaXMgMjglLCB0aGF0IGlzIGFib3V0IDMzJSBhcyBleHBlY3RlZC4NCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gRkFMU0UsIGNvbW1lbnQgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9DQojIGxpYnJhcnkoZGV2dG9vbHMpDQojc291cmNlX3VybCgnaHR0cHM6Ly9naXN0LmdpdGh1YnVzZXJjb250ZW50LmNvbS9mYXdkYTEyMy83NDcxMTM3L3Jhdy80NjZjMTQ3NGQwYTUwNWZmMDQ0NDEyNzAzNTE2YzM0ZjFhNDY4NGE1L25uZSN0X3Bsb3RfdXBkYXRlLnInKQ0KI2xpYnJhcnkobm5ldCkNCiNzZXQuc2VlZCgxOCkNCiNpcm5uIDwtIG5uZXQoU3BlY2llcyB+IC4sIGRhdGEgPSBpcmlzX3RyYWluLCBzaXplID0gMSwgbWF4aXQgPSAwKQ0KIyBwbG90Lm5uZXQoaXJubikNCg0KYGBgDQohW10oLi9SYW5kb20gTmV1cmFsIE5ldHdvcmsuUE5HKQ0KDQoNCiMjIyMjIEZpZ3VyZSA1IC0gVGhlIFJlc3VsdCBvZiB1bnRyYWluZWQgTmV1cmFsIE5ldHdvcmsgYXJlIGJhc2ljYWxseSBhcyBnb29kIGFzIHJhbmRvbSBjaG9pY2VzDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgaXJwcmVkIDwtIHByZWRpY3QoaXJubiwgaXJpc190ZXN0LCB0eXBlID0gImNsYXNzIikNCiMgdGFibGUoaXJpc190ZXN0JFNwZWNpZXMsIGlycHJlZCkNCiMgc3VtKGlyaXNfdGVzdCRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190ZXN0JFNwZWNpZXMpDQoNCg0KYGBgDQoNClRoaXMgaXMgYWNjb3JkaW5nIHRvIG91ciBpbnR1dGlvbiwgaWYgeW91IGRvbid0IGtub3cgYW55dGhpbmcgYWJvdXQgYSB0b3BpYywgeW91IGFyZSBnb2luZyB0byBwcm92aWRlIGFuc3dlcnMgd2l0aCB0aGUgc2FtZSBjb3JyZWN0bmVzcyBvZiByYW5kb20gYW5zd2VyLg0KDQojIyMjIFRoZSBOZXVyYWwgTmV0d29yayBhZnRlciBvbmUgbGVhcm5pbmcgY3ljbGUNCg0KSW4gb3JkZXIgdG8gaW1wcm92ZSwgdGhlIE5ldXJhbCBOZXR3b3JrIG11c3QgYmUgZmVkIHdpdGggZXhhbXBsZXMsIGFzIHN0YXRlZCBiZWZvcmUgd2UgbXVzdCBnbyB0aHJvdWdoIHRoZSB0cmFpbmluZyBzdGVwcyB0byBhZGp1c3Qgd2VpZ2h0cyBhbmQgbWluaW1pemUgdGhlIGVycm9ycy4gTGV0J3Mgc2VlIGhvdyB0aGUgTmV1cmFsIE5ldHdvcmsgaW1wcm92ZXMgZ29pbmcgdGhyb3VnaCBvbmUgc2luZ2xlIG1pbmltaXphdGlvbiBjeWNsZSwgdGhhdCBpcyBnb2luZyB0aHJvdWdoIHRoZSAxMDAgdGVzdCBmbG93ZXJzIG9ubHkgb25jZS4gDQoNClRoZSByZXN1bHRpbmcgTmV0d29yayBhbmQgcmVzdWx0cyB3aXRoIHRlc3QgZGF0YSBhcyBpbnB1dCBpcyBpbiB0aGUgZm9sbG93aW5nIHBpY3R1cmUuDQoNCiFbXSguLzFjeWNsZU5OLlBORykNCg0KIyMjIyMgRmlndXJlIDYgLSBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgb25lIGN5Y2xlIHRyYWluaW5nDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQojIGxpYnJhcnkobm5ldCkNCiMgc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAxLCBtYXhpdCA9IDEpDQojIGlycHJlZCA8LSBwcmVkaWN0KGlybm4sIGlyaXNfdGVzdCwgdHlwZSA9ICJjbGFzcyIpDQoNCiMgdGFibGUoaXJpc190ZXN0JFNwZWNpZXMsIGlycHJlZCkNCiMgc3VtKGlyaXNfdGVzdCRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190ZXN0JFNwZWNpZXMpDQpgYGANCg0KIyMjIyBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgc2V2ZXJhbCBsZWFybmluZyBjeWNsZXMNCg0KQXMgdGhlIGZpcnN0IGxlYXJuaW5nIGN5Y2xlIGRpZG4ndCBpbXByb3ZlIHRoZSByZXN1bHQsIHNvIGxldCB0aGUgTmV1cmFsIE5ldHdvcmsgcGxheSBhbmQgcGxheSBhZ2FpbiB3aXRoIHRoZSBkYXRhIHNldCBhcyBSb21hbnMgc2FpZCAiUmVwZXRpdGEgSXV2YW50IjogcmVwZWF0aW5nIHRoaW5ncyBoZWxwcyEgTGV0J3MgYXBwbHkgdGhlIGRlZmF1bHQgMTAwIHJlcGV0aXRpb24uDQpBZnRlciB0aGlzIHRyYWluaW5nLCB0aGUgcGFyYW1ldGVycyB0dW5pbmcgbGVkIHRvIGFuIGltcHJvdmVtZW50LiBOb3cgdGhlIGFjY3VyYWN5IGlzIDU0JS4gU2VlIHRoZSBmb2xsb3dpbmcgcGljdHVyZS4NCg0KIVtdKC4vTWFueWN5Y2xlc05OLlBORykNCg0KIyMjIyMgRmlndXJlIDcgLSBUaGUgTmV1cmFsIE5ldHdvcmsgYWZ0ZXIgbWFueSBjeWNsZSB0cmFpbmluZy4NCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Kc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAxKQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3RyYWluLCB0eXBlID0gImNsYXNzIikNCg0KDQojIHRhYmxlKGlyaXNfdHJhaW4kU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190cmFpbiRTcGVjaWVzID09IGlycHJlZCkgLyBsZW5ndGgoaXJpc190cmFpbiRTcGVjaWVzKQ0KDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3Rlc3QsIHR5cGUgPSAiY2xhc3MiKQ0KIyB0YWJsZShpcmlzX3Rlc3QkU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190ZXN0JFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3Rlc3QkU3BlY2llcykNCmBgYA0KDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgcGxvdC5ubmV0KGlybm4pDQpgYGANCg0KIyMjIFRoZSBOZXVyYWwgTmV0d29yayB3aXRoIHRocmVlIGhpZGRlbiBub2Rlcw0KDQpBcyB0aGUgQWNjdXJhY3kgaXMgcXVpdGUgbG93IGZvciB0aGUgb25lIG5vZGUgaGlkZGVuIG5ldHdvcmssIGxldCdzIHRyeSB3aXRoIGEgbW9yZSBjb21wbGV4IE5ldXJhbCBOZXR3b3JrLCBpbiB0aGlzIGNhc2Ugd2UgaW5jcmVhc2UgdGhlIG51bWJlciBvZiBOZXVyYWwgTm9kZXMgaW4gdGhlIGhpZGRlbiBsYXllciB0byAzIGFuZCBwZXJmb3JtIHNldmVyYWwgY3ljbGVzIGxlYXJuaW5nLiANCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgc2V0LnNlZWQoMTgpDQojIGlybm4gPC0gbm5ldChTcGVjaWVzIH4gLiwgZGF0YSA9IGlyaXNfdHJhaW4sIHNpemUgPSAzKQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3RyYWluLCB0eXBlID0gImNsYXNzIikNCg0KDQojIHRhYmxlKGlyaXNfdHJhaW4kU3BlY2llcywgaXJwcmVkKQ0KI3N1bShpcmlzX3RyYWluJFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3RyYWluJFNwZWNpZXMpDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KIyBpcnByZWQgPC0gcHJlZGljdChpcm5uLCBpcmlzX3Rlc3QsIHR5cGUgPSAiY2xhc3MiKQ0KIyB0YWJsZShpcmlzX3Rlc3QkU3BlY2llcywgaXJwcmVkKQ0KIyBzdW0oaXJpc190ZXN0JFNwZWNpZXMgPT0gaXJwcmVkKSAvIGxlbmd0aChpcmlzX3Rlc3QkU3BlY2llcykNCg0KYGBgDQoNCkFzIHlvdSBjYW4gc2VlIGluIHRoZSBmb2xsb3dpbmcgcGljdHVyZSwgdGhlIHRocmVlIGhpZGRlbiBub2RlcyBOZXVyYWwgTmV0d29yayBpcyBkb2luZyBtdWNoIGJldHRlciB0aGFuIHRoZSBwcmV2aW91cyBvbmUsIHJlYWNoaW5nIGFuIGFjY3VyYWN5IG9mIDk2JS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgcGxvdC5ubmV0KGlybm4pDQpgYGANCg0KIVtdKC4vVGhyZWVOb2Rlc05OLlBORykNCg0KIyMjIyMgRmlndXJlIDggLSBUaGUgTmV1cmFsIE5ldHdvcmsgd2l0aCB0aHJlZSBub2RlcyBpbiB0aGUgaGlkZGVuIGxheWVyDQoNCk5vdGUgdGhhdCBpbiB0aGlzIGNhc2Ugd2UgZGlkbid0IHdyaXRlIHRoZSB3ZWlnaHRzIGluIHRoZSBwaWN0dXJlIGZvciBncmFwaGljYWwgcmVhc29ucywgaG93ZXZlciB5b3UgY2FuIHJlY29nbml6ZSB0aGUgaW5jcmVhc2VkIG51bWJlciBvZiBsaW5rcywgc28gdGhhdCB0aGUgd2VpZ2h0cyB0byBiZSBvcHRpbWl6ZWQgaW4gdGhpcyBjYXNlIGlzIGVxdWFsIHRvIDI3LiBUaGUgdGlja2VyIHRoZSBsaW5lIGluIHRoZSBwaWN0dXJlIHRoZSBncmVhdGVyIHRoZSB3ZWlnaHQgaXMuIA0KDQpUaGUgaW5jcmVhc2VkIGNvbXBsZXhpdHkgb2YgdGhlIE5ldXJhbCBOZXRvd29yayBwcm92aWRlcyBpbXByb3ZlZCByZXN1bHQuIFRoaXMgaXMgYWNjb3JkaW5nIHRvIG91ciBpbnR1dGlvbiBhbmQgY29tbW9uIHNlbnNlLCBzbyBvbmUgY2FuIGV4cGVjdCB0aGF0IHJlY29nbml6aW5nIGFuIGltYWdlIHJlcXVpcmVzIG11Y2ggbW9yZSBjb21wbGV4IE5ldXJhbCBOZXR3b3JrLg0KDQojIDYuIERpZCB0aGUgTmV1cmFsIE5ldHdvcmsgZG8gYmV0dGVyIHRoYW4geW91Pw0KDQppdCBpcyB2ZXJ5IGxpa2VseSB0aGF0IHRoZSBzaW1wbGUgb25lIGhpZGRlbiBsYXllciB0aHJlZSBub2RlcyBOZXVyYWwgTmV0d29yayBkaWQgYmV0dGVyIHRoYW4geW91IGluIElyaXMgY2xhc3NpZmljYXRpb24uIEJ1dCBob3cgY2FuIGEgMTIgbm9kZXMgLSAyNyB3ZWlnaHRzIE5ldXJhbCBOZXR3b3JrIGRvIGJldHRlciB0aGFuIGEgSHVtYW4gQnJhaW4gY29uc2lzdGluZyBvZiBhYm91dCAkMTBeezExfSQgTmV1cm9ucyBFQUNIIHdpdGggYWJvdXQgJDEwXns0fSQgDQp3ZWlnaHRzPw0KDQpUaGlzIGlzIGJlY2F1c2UgdGhlIGNsYXNzaWZpY2F0aW9uIGhlcmUgaXMgYmFzZWQgb24gbWVhc3VyZXMsIHRoYXQgYXJlIG51bWJlcnMgd2hlcmUgY29tcHV0ZXIgYXJlIG11Y2ggYmV0dGVyIHRoZW4gdXMuIEJ1dCBudW1iZXJzIGFyZSBub3QgdGhlICJyZWFsIiB3b3JsZCwgdGhleSBhcmUgYWJzdHJhY3Rpb25zIG9mIGl0LiBIdW1hbiBCcmFpbiBpbiBjb250cmFzdCBpcyBleGNlbGxlbnQgdG8gd29yayB3aXRoIHRoZSByZWFsIHdvcmxkLCB0aGF0IGlzIG9uIGFjdHVhbCBmbG93ZXJzIGltYWdlcyByYXRoZXIgdGhhbiBtZWFzdXJlcyBvZiBpdC4NCg0KDQojIDcuIENvbmNsdXNpb25zDQoNCioqV2hhdCB3ZSBkaWQqKjoNCndlIGV4cGxhaW5lZCB0aGUgYXJjaGl0ZWN0dXJlIG9mIE5ldXJhbCBOZXR3b3JrIGFuZCB3ZSBoYXZlIHRyYWluZWQgdHdvIHNpbXBsZSBOZXVyYWwgTmV0d29ya3MgYmFzZWQgb24gZGF0YSBhYm91dCBob3cgdG8gY2xhc3NpZnkgdGhlIElyaXMgc3BlY2llcyBiYXNlZCBvbiBzZXBhbC1wZXRhbCBsZW5ndGggYW5kIHdpZHRoLiBOb3RlIHRoYXQgdGhpcyB0YXNrIGlzIGluIHRoZSBhcmVhIG9mIE5hcnJvdyBBcnRpZmljaWFsIEludGVsbGluZ2VuY2UsIHRoYXQgaXMgYWJvdXQgZG9pbmcgc3BlY2lmaWMsIHZlcnkgd2VsbCBkZWZpbmVkIHRhc2tzLg0KDQoqKk5ldXJhbCBOZXR3b3JrIGxlYXJuIGJ5IGl0c2VsZioqOg0KV2UgaGF2ZSBzZWVuIHRoYXQgd2UgY2FuIHRyYWluIGEgTmV1cmFsIE5ldHdvcmsganVzdCBieSAic2hvd2luZyIgZXhhbXBsZXMsIHRoZXJlIGlzIG5vIG5lZWQgdG8gYWN0dWFsbHkgdGVhY2ggTmV1cmFsIE5ldHdvcmsgaG93IHRvIGRvIHRoaW5ncywgbm8gbmVlZCB0byBjb2RlIGNvbXBsZXggYWxnb3JpdGhtcyBpbiBjb21wdXRlciBwcm9ncmFtLiBBZnRlciB0aGUgdHJhaW5pbmcgaXMgZG9uZSwgdGhlIE5ldXJhbCBOZXR3b3JrIGNhbiBmYWNlIHJlYWwgbmV3IGNhc2VzLCBhbmQgYXBwbHkgdG8gdGhlbSB3aGF0IGl0IGxlYXJudC4gVGhlIE5ldXJhbCBOZXR3b3JrIGxlYXJucyBieSBpdHNlbGYuDQoNCioqSG93IE5ldXJhbCBOZXR3b3JrIGxlYXJucyoqOg0KV2UgaGF2ZSBzaG93biB0aGF0IHRyYWluaW5nIGEgTmV0d29yayBtZWFucyBhY3R1YWxseSBvcHRpbWl6aW5nIHRoZSB3ZWlnaHRzIG9mIHRoZSBjb25uZWN0aW9ucywgb25jZSB3ZSBoYXZlIHNlbGVjdGVkIGhvdyBtYW55IGhpZGRlbiBsYXllcnMsIGhvdyBtYW55IG5vZGVzIHBlciBoaWRkZW4gbGF5ZXIgd2Ugd2FudCBhbmQgdGhlIGFjdGl2YXRpb24gZnVuY3Rpb24gdG8gYmUgdXNlZC4gRm9yIHRoZSBzYWtlIG9mIHNpbXBsaWNpdHkgd2UgZGlkbid0IGNvdmVyIHRoZSBhbGdvcml0aG1zIHRvIG9wdGltaXplIHRoZSB3ZWlnaHRzLCBjYWxsZWQgc3RvY2hhc3RpYyBncmFkaWVudCBkZXNjZW50IHdpdGggYmFja3Byb3BhZ2F0aW9uIHRlY2huaXF1ZS4NCg0KKipNb3JlIGNvbXBsZXggTmV1cmFsIE5ldHdvcmsgY2FuIGRvIGJldHRlcioqOg0KV2Ugc2hvd2VkIGhvdyBtb3JlIGNvbXBsZXggTmV1cmFsIE5ldHdvcmsgY2FuIGRvIGJldHRlciB0aGFuIHNpbXBsZSBvbmVzLCBpbiBvdXIgY2FzZSB3ZSBtb3ZlZCBmcm9tIDU0JSBhY2N1cmFjeSB3aXRoIGEgb25lIGhpZGRlbiBuZXVyYWwgbm9kZSB0byA5NiUgYWNjdXJhY3kgd2l0aCB0aHJlZSBoaWRkZW4gbmV1cmFsIG5vZGVzLg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=